/*Main*/ 
#include "stdafx.h"
#include "Test.h"
#include "LinearSenseBarrier.h"

using namespace std;

/*
 * Impl of the pure virtual function.  
 */	
void LinearSenseBarrier::await() {
    int me = threadId->get();
    int mySense = threadSense->get();

    if ( me == (_size - 1) ) { // im first - no need to wait for prev
		_threadDoneArray[me].set(true);
    } else {
      int prevIdx = me + 1;
	  while (!_threadDoneArray[prevIdx].get()) 
	  {
		  //Thread::yield(); // use this when working on core2 due
	  }

      if ( me == 0 ) {
        for (int i = (_size - 1) ; i >= 0 ; i--) {
			_threadDoneArray[i].set(false);
        }
        _sense = mySense; 
        threadSense->set((mySense + 1) % 2);
        return;
        
      } else {
		  _threadDoneArray[me].set(true);
      }
    }

	while (_sense != mySense) 
	{
		//Thread::yield(); // use this when working on core2 due machine
	} // busy-wait

    threadSense->set((mySense + 1) % 2); // reset my sense for next phase

	mySense = threadSense->get();
	flush(cout);
}

void LinearSenseBarrier::initThreadLocals(int me)
{
	threadId->set(me);
}

LinearSenseBarrier *g_bar = new LinearSenseBarrier(Globals::numberOfThreads);

// MAIN
// first arg	= number of threads
// second arg	= max count to 
// third arg	= number of iterations 
// forth arg	= test type 0=counter, 1=localCounter 2=matrix
// fifth arg	= shared memory - 1 for shared mem, 0 for local mem.
// sixth arg	= barrier type. 0=SenseWithWait, 1=LinearSense, 2=BinaryStaticBarrier
int main(int argc,char* argv[])
{
	TestFactory factory;
	TestType testType = Counter; // default test type
	if (argc > 1)
	{
		Globals::numberOfThreads = atoi(argv[1]);
	}
	
	if (argc > 2)
	{
		Globals::countTo = atoi(argv[2]);
	}

	if (argc > 3)
	{
		Globals::numberOfIterations = atoi(argv[3]);
	}

	if (argc > 4)
	{
		int typeId = atoi(argv[4]);
		if (typeId == 0)
		{
			testType = Counter;
		} else if (typeId == 1)
		{
			testType = LocalCounter;
		} else if (typeId == 2)
		{
			testType = Matrix;
		} else {
			printf("Unsupported TestType id: %d. Exiting.\n", typeId);
			assert(false);
		}
	}

	printf("LinearSenseBarrier, Number of threads, %d, count to, %d, numOfIters:,%d\n", Globals::numberOfThreads, Globals::countTo, Globals::numberOfIterations);
	fflush(stdout);
	g_bar = new LinearSenseBarrier(Globals::numberOfThreads);

	Test* test = factory.createTest(g_bar, testType);
	
	test->performTest();
}


